
/**
 *	\file Definition of the nmn::output_message function.
 *	\author Sean Tromans
 */

#ifndef	NMN_OUTPUT_MESSAGE_HPP
#define	NMN_OUTPUT_MESSAGE_HPP

#ifndef	NMN_OUTPUT_MESSAGES_ON
#define	NMN_OUTPUT_MESSAGES_ON 1
#endif	//NMN_OUTPUT_MESSAGES_ON

#if NMN_OUTPUT_MESSAGES_ON

#include <needs_more_ninja/template/create_string.hpp>
#include <iostream>

#if		defined(WIN32)
#include <windows.h>
#else
#error Unrecognised platform
#endif

#define	NMN_DEFINE_OUTPUT_MESSAGE(z, n, _)	\
	template < typename char_t, typename traits_t, typename allocator_t, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), class T) >	\
	inline void	output_message( typename std::basic_string< char_t, traits_t, allocator_t > const & format, BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(n), T, const & p) )	\
	{	\
		nmn::output_message( nmn::create_string( format, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), p) ) );	\
	}	\
	\
	template < typename char_t, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), class T) >	\
	inline void output_message( typename char_t const * const format, BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(n), T, const & p) )	\
	{	\
		nmn::output_message( nmn::create_string( format, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), p) ) );	\
	}

namespace nmn
{

	namespace detail
	{
#if	defined(WIN32)

		/**
		Helper function to output the debig message using the correct windows function.
		@param message The message to display.
		\author Sean Tromans
		*/
		template < typename char_t, typename traits_t, typename allocator_t >
		void console_output( typename std::basic_string< char_t, traits_t, allocator_t > const & message )
		{
			static_assert( false, "Unsupported character type." );
		}

		template < typename traits_t, typename allocator_t >
		void console_output( typename std::basic_string< char, traits_t, allocator_t > const & message )
		{
			std::cout << message << std::endl;

			OutputDebugStringA( message.c_str( ) );
			OutputDebugStringA( "\n" );
		}

		template < typename traits_t, typename allocator_t >
		void console_output( typename std::basic_string< wchar_t, traits_t, allocator_t > const & message )
		{
			std::wcout << message << std::endl;

			OutputDebugStringW( message.c_str( ) );
			OutputDebugStringW( L"\n" );
		}

#else
#error Unrecognised Platform
#endif
	}

	/**
	 *	Creates a string via nmn::create_string and outputs it to the console or debug window.
	 *	@param format The format the string should take.
	 *	@return The generated string.
	 *	\author Sean Tromans
	 */
	template < typename char_t, typename traits_t, typename allocator_t >
	inline void output_message( typename std::basic_string< char_t, traits_t, allocator_t > const & format )
	{
		detail::console_output( format );
	}

	template < typename char_t >
	inline void output_message( typename char_t const * const format )
	{
		output_message( std::basic_string< char_t >( format ) );
	}

	BOOST_PP_REPEAT( BOOST_PP_INC(NMN_CREATE_STRING_TOTAL_PARAMS), NMN_DEFINE_OUTPUT_MESSAGE, 0 );

};

#undef	NMN_DEFINE_OUTPUT_MESSAGE

#else

namespace nmn
{
	inline void	output_message(...)
	{
	}
};

#endif

#endif	//NMN_OUTPUT_MESSAGE_HPP
